﻿// 1.1.7.12. Write a program, which creates square matrices like those in the figures below and prints them
// formatted to the console. The size of the matrices will be read from the console.
// See the examples for matrices with size of 4 x 4 and make the other sizes in a similar fashion:
//     1 5  9 13     1 8  9 16     7 11 14 16     1 12 11 10
//  a) 2 6 10 14  b) 2 7 10 15  c) 4  8 12 15  d) 2 13 16  9
//     3 7 11 15     3 6 11 14     2  5  9 13     3 14 15  8
//     4 8 12 16     4 5 12 13     1  3  6 10     4  5  6  7

using System;

class FourTypesOfSquareMatrice
{
    private static char CorrectTypeInput()
    {
        char type = '\u0000';
        bool correctType = false;
        do
        {
            Console.Write("Pick a type ('a', 'b', 'c' or 'd'): ");
            string userInput = Console.ReadLine();
            correctType = char.TryParse(userInput, out type);
        } while (correctType == false);
        return type;
    }
    private static uint CorrectSizeInput()
    {
        uint size = 0u;
        bool correctSize = false;
        do
        {
            Console.Write("Choose a size (size > 0): ");
            string userInput = Console.ReadLine();
            correctSize = uint.TryParse(userInput, out size);
        } while (correctSize == false);
        return size;
    }
    private static void ConstructMatriceA(uint size, int[,] matrice)
    {
        for (int col = 0; col < size; col++)
        {
            for (int row = 0; row < size; row++)
            {
                int stepper = ((col * (int)size) + 1) + row;
                matrice[row, col] = stepper;
            }
        }
    }
    private static void ConstructMatriceB(uint size, int[,] matrice)
    {
        for (int col = 0; col < size; col++)
        {
            if (col % 2 == 0)
            {
                for (int row = 0; row < size; row++)
                {
                    int stepper = ((col * (int)size) + 1) + row;
                    matrice[row, col] = stepper;
                }
            }
            else
            {
                for (int row = (int)size - 1, counter = 0; row >= 0; row--)
                {
                    int stepper = ((col * (int)size) + 1) + counter;
                    matrice[row, col] = stepper;
                    counter++;
                }
            }            
        }
    }
    private static void ConstructMatriceC(uint size, int[,] matrice)
    {
        int startPositionX = 0;
        int startPositionY = (int)size - 1;
        int stepper = 1;
        do
        {
            int currentPositionX = startPositionX;
            int currentPositionY = startPositionY;
            while (currentPositionX < size && currentPositionY < size)
            {
                matrice[currentPositionY, currentPositionX] = stepper;
                stepper++;
                currentPositionX++;
                currentPositionY++;
            }
            if (startPositionY != 0)
            {
                startPositionY--;
            }
            else
            {
                startPositionX++;
            }
        } while (stepper <= size * size);
    }
    private static void ConstructMatriceD(uint size, int[,] matrice)
    {
        int stepper = 1;
        int row = 0;
        int col = 0;
        int endRightCol = (int)size - 1;
        int endDownRow = (int)size - 1;
        int endLeftCol = 1;
        int endUpRow = 0;
        while (true)
        {
            for (row = row; row <= endDownRow; row++)   // down
            {
                matrice[row, col] = stepper;
                stepper++;
            }
            row--;
            endDownRow--;
            col++;
            for (col = col; col <= endRightCol; col++)  // right
            {
                matrice[row, col] = stepper;
                stepper++;
            }
            col--;
            endRightCol--;
            row--;
            for (row = row; row >= endUpRow; row--) // up
            {
                matrice[row, col] = stepper;
                stepper++;
            }
            if (stepper > size * size)
            {
                break;
            }
            row++;
            endUpRow++;
            col--;
            for (col = col; col >= endLeftCol; col--)   // left
            {
                matrice[row, col] = stepper;
                stepper++;
            }
            col++;
            endLeftCol++;
            row++;
        }
    }
    private static void PrintMatrice(uint size, int[,] matrice)
    {
        for (int row = 0; row < size; row++)
        {
            for (int col = 0; col < size; col++)
            {
                Console.Write("{0, -3}", matrice[row, col]);
            }
            Console.WriteLine();
        }
    }
    static void Main()
    {
        while (true)
        {
            char type = CorrectTypeInput();
            uint size = CorrectSizeInput();
            int[,] matrice = new int[size, size];

            if (type == 'a')
            {
                ConstructMatriceA(size, matrice);
                PrintMatrice(size, matrice);
            }
            else if (type == 'b')
            {
                ConstructMatriceB(size, matrice);
                PrintMatrice(size, matrice);
            }
            else if (type == 'c')
            {
                ConstructMatriceC(size, matrice);
                PrintMatrice(size, matrice);
            }
            else if (type == 'd')
            {
                ConstructMatriceD(size, matrice);
                PrintMatrice(size, matrice);
            }
            else
            {
                Console.WriteLine("There is no such a type of matrice");
            }
        }
    }
}